package com.duoqin.common.utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.duoqin.account.DuoqinAccount;
import com.duoqin.common.base64.Base64;
import com.duoqin.guard.utils.GuardUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;
import java.util.Date;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Utils {
    private static final String TAG = "duoqin_Util";
    private final static char[] hexArray = "0123456789abcdef".toCharArray();

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
    public static String timestamp() {
        return String.valueOf(System.currentTimeMillis());
    }

    public static String checksum_HmacSHA1(String content, String key) {
        return checksum_hmac(content, key, "HmacSHA1");
    }

    public static String checksum_HmacSHA256(String content, String key) {
        return checksum_hmac(content, key, "HmacSHA256");
    }

    public static String checksum_hmac(String content, String key, String algorithm) {
        try {
            Mac mac = Mac.getInstance(algorithm);
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), mac.getAlgorithm());
            mac.init(keySpec);
            String checksum = bytesToHex(mac.doFinal(content.getBytes()));
            return checksum;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String md5sum(byte[] content, int offset, int len) {
        try {
            Log.w(TAG, "length: " + content.length);
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(content, offset, len);

            byte[] result = digest.digest();
            String checksum = bytesToHex(result);
            return checksum;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    //版本名
    public static String getVersionName(Context context) {
        return getPackageInfo(context).versionName;
    }

    //版本号
    public static int getVersionCode(Context context) {
        return getPackageInfo(context).versionCode;
    }

    //获取版本info
    private static PackageInfo getPackageInfo(Context context) {
        PackageInfo pi = null;

        try {
            PackageManager pm = context.getPackageManager();
            pi = pm.getPackageInfo(context.getPackageName(),
                    PackageManager.GET_CONFIGURATIONS);

            return pi;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return pi;
    }

    /**
     * 获取wav音频时长 ms
     * @param file wav音频文件
     * @return
     */
    public static long getWavLength(File file) {
        if (file != null && file.exists()) {
            try {
                FileInputStream stream = new FileInputStream(file);
                byte buffer[] = new byte[100];
                if (stream.read(buffer, 0, buffer.length) > 0) {
                    return getWavLength(buffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    /**
     * 获取wav音频时长 ms
     * @param wavdata wav音频文件字节数组
     * @return
     */
    public static long getWavLength(byte[] wavdata) {
        if (wavdata != null && wavdata.length > 44) {
            int byteRate = bytes2ToInt(wavdata, 28, 31);
            int waveSize = bytes2ToInt(wavdata, 40 , 43);
            Log.d(TAG, "getWavLength:waveSize=" + waveSize + ",byteRate=" + byteRate);
            Log.d(TAG, "getWavLength:len=" + waveSize * 1000 / byteRate);
            return waveSize * 1000 / byteRate;
        }
        return 0;
    }

    public static int bytes2ToInt(byte[] b, int start, int end){
        return ((b[end]&0xff) << 24) + ((b[end-1]&0xff) << 16) + ((b[end-2]&0xff) << 8)
                + (b[end-3]&0xff);
    }

    public static boolean areSameDay(long timeA,long timeB) {
        if (timeA <= 0 || timeB <= 0) return false;
        Calendar calDateA = Calendar.getInstance();
        calDateA.setTime(new Date(timeA));

        Calendar calDateB = Calendar.getInstance();
        calDateB.setTime(new Date(timeB));

        return calDateA.get(Calendar.YEAR) == calDateB.get(Calendar.YEAR)
                && calDateA.get(Calendar.MONTH) == calDateB.get(Calendar.MONTH)
                &&  calDateA.get(Calendar.DAY_OF_MONTH) == calDateB.get(Calendar.DAY_OF_MONTH);
    }

    // copy a file from srcFile to destFile, return true if succeed, return
    // false if fail
    public static void copyFileOrThrow(File srcFile, File destFile) throws IOException {
        try (InputStream in = new FileInputStream(srcFile)) {
            copyToFileOrThrow(in, destFile);
        }
    }

    /**
     * Copy data from a source stream to destFile.
     * Return true if succeed, return false if failed.
     */
    public static void copyToFileOrThrow(InputStream inputStream, File destFile)
            throws IOException {
        if (destFile.exists()) {
            destFile.delete();
        }
        FileOutputStream out = new FileOutputStream(destFile);
        try {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) >= 0) {
                out.write(buffer, 0, bytesRead);
            }
        } finally {
            out.flush();
            try {
                out.getFD().sync();
            } catch (IOException e) {
            }
            out.close();
            inputStream.close();
        }
    }

    // 清空文件夹里的文件，仅当前文件夹，不递归
    public static void clearFolderFiles(String dirPath){
        try {
            File dir = new File(dirPath);
            if (dir.isDirectory()) {
                File[] files = dir.listFiles();
                if (null != files) {
                    for (File file : files) {
                        if (!file.isDirectory()) {
                            file.delete();
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static long getVoiceDuration(String path) {
        MediaPlayer mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource(path);
            mediaPlayer.prepare();
            return mediaPlayer.getDuration();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            mediaPlayer.release();
        }
        return 0;
    }

    /**
     * 得到amr的时长
     *
     * @param file
     * @return amr文件时间长度
     * @throws IOException
     */
    public static long getAmrDuration(File file) throws IOException {
        long duration = -1;
        int[] packedSize = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0,
                0, 0 };
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(file, "rw");
            // 文件的长度
            long length = file.length();
            // 设置初始位置
            int pos = 6;
            // 初始帧数
            int frameCount = 0;
            int packedPos = -1;
            // 初始数据值
            byte[] datas = new byte[1];
            while (pos <= length) {
                randomAccessFile.seek(pos);
                if (randomAccessFile.read(datas, 0, 1) != 1) {
                    duration = length > 0 ? ((length - 6) / 650) : 0;
                    break;
                }
                packedPos = (datas[0] >> 3) & 0x0F;
                pos += packedSize[packedPos] + 1;
                frameCount++;
            }
            // 帧数*20
            duration += frameCount * 20;
        } finally {
            if (randomAccessFile != null) {
                randomAccessFile.close();
            }
        }
        return duration; // (int)((duration/1000)+1);
    }

    public static String downloadFile(String uriString, String filePath) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            File file = new File(filePath);
            if (file.exists()) {
                file.delete();
            }
            URL url = new URL(uriString);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            inputStream = connection.getInputStream();
            outputStream = new FileOutputStream(file);
            byte[] buffer = new byte[4*1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) >= 0) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();
            return file.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static String getDeviceToken(Context context) {
        TelephonyManager telephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("imei", telephonyMgr.getDeviceId());
            jsonObject.put("account", DuoqinAccount.getAccountName(context));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        try {
            Log.i(TAG, "device token json = " + jsonObject.toString());
            return Base64.encodeBase64URLSafeString(jsonObject.toString().getBytes(GuardUtil.CHARSET));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }
}
